package com.wman.a12_scalable;

import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.OverScroller;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.view.GestureDetectorCompat;

/**
 * Name     wman
 * Anthor   wman
 * Time     2020/10/17 0017 17:20
 * Describe 描述
 */
public class ScalableImageView extends View implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, Runnable {

    public static final float IMAGE_WIDTH = Utils.dpToPixel(300);
    public static final float OVER_SCALE = 1.5f;
    private Bitmap mBitmap;
    private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

    private float offsetX, offsetY;
    private float originalOffsetX, originalOffsetY;
    private float smallScale, bigScale;
    private boolean isBig;
    private float scaleFraction;
    private ObjectAnimator mScaleAnimator;
    private GestureDetectorCompat mDetector;
    private OverScroller mScroller;

    private float getScaleFraction() {
        return scaleFraction;
    }

    private void setScaleFraction(float scaleFraction) {
        this.scaleFraction = scaleFraction;
        invalidate();
    }

    private ObjectAnimator getScaleAnimator() {
        if (mScaleAnimator == null) {
            mScaleAnimator = ObjectAnimator.ofFloat(this, "scaleFraction", 0, 1);
        }
        return mScaleAnimator;
    }

    public ScalableImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        mBitmap = Utils.getAvatar(getResources(), (int) IMAGE_WIDTH);
        mDetector = new GestureDetectorCompat(context, this);
//        mDetector.setOnDoubleTapListener(this);
        mScroller = new OverScroller(context);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        originalOffsetX = (getWidth() - mBitmap.getWidth()) / 2f;
        originalOffsetY = (getHeight() - mBitmap.getHeight()) / 2f;

        if ((float) mBitmap.getWidth() / mBitmap.getHeight() > (float) getWidth() / getHeight()) {
            smallScale = (float) getWidth() / mBitmap.getWidth();
            bigScale = (float) getHeight() / mBitmap.getHeight() * OVER_SCALE;
        } else {
            smallScale = (float) getHeight() / mBitmap.getHeight();
            bigScale = (float) getWidth() / mBitmap.getWidth() * OVER_SCALE;
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.translate(offsetX * scaleFraction, offsetY * scaleFraction);
        float scale = smallScale + (bigScale - smallScale) * scaleFraction;
        canvas.scale(scale, scale, getWidth() / 2f, getHeight() / 2f);
        canvas.drawBitmap(mBitmap, 0 + originalOffsetX, 0 + originalOffsetY, mPaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return mDetector.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent motionEvent) {
        return true;//比返回true，接下来的时间序列就不会收到了
    }

    @Override
    public void onShowPress(MotionEvent motionEvent) {
        //onShowPress之前，都会延时100ms，不像滑动视图才有预先按下
    }

    @Override
    public boolean onSingleTapUp(MotionEvent motionEvent) {
        return false;//这些返回对我们开发没有用，只有onDown必须是true
    }

    @Override
    public boolean onScroll(MotionEvent down, MotionEvent event, float distanceX, float distanceY) {
        if (isBig) {
            offsetX -= distanceX;
            offsetX = Math.min(offsetX, (mBitmap.getWidth() * bigScale - getWidth()) / 2);
            offsetX = Math.max(offsetX, -(mBitmap.getWidth() * bigScale - getWidth()) / 2);

            offsetY -= distanceY;
            offsetY = Math.min(offsetY, (mBitmap.getHeight() * bigScale - getHeight()) / 2);
            offsetY = Math.max(offsetY, -(mBitmap.getHeight() * bigScale - getHeight()) / 2);
        }

        invalidate();
        return false;
    }

    @Override
    public void onLongPress(MotionEvent motionEvent) {

    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public boolean onFling(MotionEvent down, MotionEvent event, float v, float v1) {
        if (isBig) {
            int width = (int) ((mBitmap.getWidth() * bigScale - getWidth()) / 2);
            int height = (int) ((mBitmap.getHeight() * bigScale - getHeight()) / 2);
            mScroller.fling((int) offsetX, (int) offsetY, (int) v, (int) v1,
                    -width, width, -height, height, 50, 50);

            postOnAnimation(this);
        }

        return false;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
        return false;
    }

    @Override
    public boolean onDoubleTap(MotionEvent event) {
        isBig = !isBig;
        if (isBig) {
            offsetX = ((event.getX() - getWidth()) / 2f) - (event.getX() - getWidth()) * bigScale / smallScale;
            offsetY = ((event.getY() - getHeight()) / 2f) - (event.getY() - getHeight()) * bigScale / smallScale;
            getScaleAnimator().start();
        } else {
            getScaleAnimator().reverse();
        }
        return false;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent motionEvent) {
        return false;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
    @Override
    public void run() {
        if (mScroller.computeScrollOffset()) {
            offsetX = mScroller.getCurrX();
            offsetY = mScroller.getCurrY();
            invalidate();
            postOnAnimation(this);
        }
    }
}
